#pragma once
#include "util.hpp"
#include <cstdlib>
#include <mutex>
#include <mysql/mysql.h>

namespace aod
{
    #define HOST "127.0.0.1"
    #define USER "root"
    #define PASS ""
    #define NAME "aod_system"

    static MYSQL* mysqlInit()
    {
        MYSQL* _mysql = mysql_init(NULL);
        if(_mysql == NULL)
        {
            std::cout << "MySQL初始化失败" << std::endl;
            return NULL;
        }
        if(mysql_real_connect(_mysql,HOST,USER,PASS,NAME,0,NULL,0) == NULL)
        {
            std::cout << "连接MySQL失败" << std::endl;
            std::cout << mysql_error(_mysql) << std::endl;
            return NULL;
        }
        mysql_set_character_set(_mysql,"utf8");
        return _mysql;
    }

    static bool mysqlQuery(MYSQL* _mysql,const std::string& sql)
    {
        int ret = mysql_query(_mysql,sql.c_str());
        if(ret != 0)
        {
            std::cout << sql << std::endl;
            std::cout << mysql_error(_mysql) << std::endl;
            return false;
        }
        return true;
    }
    static void mysqlDestroy(MYSQL* _mysql)
    {
        if(_mysql != nullptr)
        {
            mysql_close(_mysql);
        }
    }

    class TableVideo
    {
    private:
        MYSQL* _mysql;
        std::mutex _mtx;
    public:
        TableVideo()
        {
            _mysql = mysqlInit();
            if(_mysql == NULL)
            {
                exit(-1);
            }
        }
        ~TableVideo()
        {
            mysqlDestroy(_mysql);
        }
        //插入视频相关信息至数据库
        bool insert(const Json::Value& video)
        {
            // id name info video image
            std::string sql;
            sql.resize(4096+video["info"].asString().size());
            #define INSERT_VIDEO "insert into tb_video values(null,%s,%s,%s,%s);"
            sprintf(&sql[0],INSERT_VIDEO,video["name"].asCString(),
            video["info"].asCString(),video["video"].asCString(),video["image"].asString());
            return mysqlQuery(_mysql,sql);
        }
        //修改具体某个视频的相关信息
        bool update(int video_id,Json::Value& video)
        {
            // id name info video image
            std::string sql;
            sql.resize(4096+video["info"].asString().size());
            #define UPDATE_VIDEO "update tb_video set name='%s',info='%s' where id=%d;"
            sprintf(&sql[0],UPDATE_VIDEO,video["name"].asCString(),video["info"].asCString(),video_id);
            return mysqlQuery(_mysql,sql);
        }
        //删除具体某个视频的相关信息
        bool Delete(int video_id)
        {
            // id name info video image
            std::string sql;
            sql.resize(1024);
            #define DELETE_VIDEO "delete from tb_video where id=%d;"
            sprintf(&sql[0],DELETE_VIDEO,video_id);
            return mysqlQuery(_mysql,sql);
        }
        //查询所有的视频相关信息
        bool SelectAll(Json::Value* videos)
        {
            // id name info video image
            #define SELECT_ALL "select * from tb_video;"
            _mtx.lock();
            bool ret = mysqlQuery(_mysql,SELECT_ALL);
            if(ret == false)
            {
                std::cout << "执行mql语句失败：" << SELECT_ALL << std::endl;
                _mtx.unlock();
                return false;
            }
            MYSQL_RES* res = mysql_store_result(_mysql);
            if(res == nullptr)
            {
                std::cout << "执行mql语句失败：" << SELECT_ALL << std::endl;
                _mtx.unlock();
                return false;
            }
            _mtx.unlock();
            int num_rows = mysql_num_rows(res);
            for(int i = 0;i < num_rows;i++)
            {
                MYSQL_ROW row =mysql_fetch_row(res);
                Json::Value video;
                video["id"] = atoi(row[0]);
                video["name"] = row[1];
                video["info"] = row[2];
                video["video"] = row[3];
                video["image"] = row[4];
                videos->append(video);
            }
            mysql_free_result(res);
            return true;
        }
        //查询具体某一个视频的相关信息
        bool SelectOne(int video_id , Json::Value* video)
        {
            // id name info video image
            #define SELECT_ONE "select * from tb_video where id=%d;"
            std::string sql;
            sql.resize(1024);
            sprintf(&sql[0],SELECT_ONE,video_id);
            _mtx.lock();
            bool ret = mysqlQuery(_mysql,sql);
            if(ret == false)
            {
                std::cout << "执行mql语句失败：" << sql << std::endl;
                _mtx.unlock();
                return false;
            }
            MYSQL_RES* res = mysql_store_result(_mysql);
            if(res == nullptr)
            {
                std::cout << "获取mysql结果集失败" << std::endl;
                _mtx.unlock();
                return false;
            }
            _mtx.unlock();
            int num_rows = mysql_num_rows(res);
            if(num_rows != 1)
            {
                std::cout << "have no date" << std::endl;
                mysql_free_result(res);
                return false;
            }
            MYSQL_ROW row = mysql_fetch_row(res);
            (*video)["id"] = atoi(row[0]);
            (*video)["name"] = row[1];
            (*video)["info"] = row[2];
            (*video)["video"] = row[3];
            (*video)["image"] = row[4];
            mysql_free_result(res);
            return true;
        }
        //模糊查询一批视频相关信息
        bool SelectLike(const std::string& key,Json::Value* videos)
        {
            // id name info video image
            #define SELECTLIKE_VIDEO "select * from tb_video where name like '%%%s%%';"
            std::string sql;
            sql.resize(1024);
            sprintf(&sql[0],SELECTLIKE_VIDEO,key);
            _mtx.lock();
            bool ret = mysqlQuery(_mysql,sql);
            if(ret == false)
            {
                std::cout << "执行mql语句失败：" << sql << std::endl;
                _mtx.unlock();
                return false;
            }
            MYSQL_RES* res = mysql_store_result(_mysql);
            if(res == nullptr)
            {
                std::cout << "获取mysql结果集失败" << std::endl;
                _mtx.unlock();
                return false;
            }
            _mtx.unlock();
            int num_rows = mysql_num_rows(res);
            for(int i = 0;i < num_rows;i++)
            {
                MYSQL_ROW row =mysql_fetch_row(res);
                Json::Value video;
                video["id"] = atoi(row[0]);
                video["name"] = row[1];
                video["info"] = row[2];
                video["video"] = row[3];
                video["image"] = row[4];
                videos->append(video);
            }
            mysql_free_result(res);
            return true;
        }

    };

}